/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package clientClasses;

import commonClasses.Messages.NewBidBroadcastMsg;
import commonClasses.*;
import commonClasses.Messages.Msg;
import commonClasses.Messages.FinishMsg;
import commonClasses.commonInterfaces.ClientModelIntf;
import commonClasses.commonInterfaces.ItemIntf;
import commonClasses.commonInterfaces.ServerIntf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import commonClasses.commonInterfaces.ProtocolIntf;

/**
 *
 * @author MGL
 */
public class ClientService implements Runnable {

    protected final int sleepingTime = 500;
    private DataInputStream _dis;
    private DataOutputStream _dos;
    private ClientModelIntf _model;
    private ProtocolIntf _protocol;
    private Orders _orders;

    public ClientService(ProtocolIntf protocol,
            ClientModelIntf model) {
        this._protocol = protocol;
        this._model = model;
        this._orders = _protocol.getOrders();
    }

    public void run() {


        Utils.write("ClientService: Run!");
        /*
         * tu ma być pętla która ciągle działa
         * i naprzemiennie sprawdza czy serwer coś do nas wysłał
         * może to być:
         *      broadcast new bid
         *      finish którejś z aukcji
         *      i nic innego.
         *
         * drugą z rzeczy jest sprawdzanie czy w demandsach jest jakieś nowe
         * żądanie, jeżeli tak, bierze je i wykonuje dziad.
         */

        _dis = new DataInputStream(
                _protocol.getDIS());

        _dos = new DataOutputStream(
                _protocol.getDOS());

        while (_protocol.getSocket().isConnected()) {
            Utils.write("ClientService: wejście pętli");
            long msgID;

            if (_orders.isEmpty()) {
                Utils.write("ClientService: lista orderów pusta, więc śpię");
                //gdy jest pusta to troche spimy zeby nie zajmowac czasu procesora
                try {
                    Thread.sleep(sleepingTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            } else {
                Utils.write("ClientService: lista orderów zawiera " +
                        _protocol.getOrders().firstOrderType());
                InfoCarier infoCarier = _orders.getOrder();
                switch (infoCarier.getInfoType()) {
                    case getItems:
                        new GetItemsOrder(_protocol).go();
                        break;

                    case getItemDetails:
                        if (infoCarier.getParameters().get(0) instanceof Long) {
                            Long itemID = (Long) infoCarier.getParameters().get(0);
                            new GetItemDetailsOrder(_protocol, itemID).go();
                        } else {
                            Utils.write("Parametr jest innej klasy: " +
                                    infoCarier.getParameters().get(0).getClass());
                        }

                        break;

                    case login:
                        new LogOnHostOrder(_protocol).go();
                        break;

                    case enterAuction:
                        if (infoCarier.getParameters().get(0) instanceof Long) {
                            Long itemID = (Long) infoCarier.getParameters().get(0);
                            Utils.write("itemid="+itemID);
                            new EnterAuctionOrder(_protocol, itemID).go();
                        } else {
                            Utils.write("Parametr jest innej klasy: " +
                                    infoCarier.getParameters().get(0).getClass());
                        }
                        break;

                    case newBid:
                        if (infoCarier.getParameters().get(0) instanceof Long) {
                            Long itemID = (Long) infoCarier.getParameters().get(0);
                            Item item = new Item();
                            item.setBasic(itemID, new Price(MagicNumbers.CURRENCY, itemID), "");
                            new NewBidOrder(_protocol, item).go();
                        } else {
                            Utils.write("Parametr jest innej klasy: " +
                                    infoCarier.getParameters().get(0).getClass());
                        }
                        break;

                    default:
                        Utils.write("infoCarier otrzymał nie pasujący stuff.");
                }
            }

            int availiable = 0;
            try {
                availiable = _dis.available();

            } catch (IOException e) {
                e.printStackTrace();
            }

            if (availiable > 0) {

                try {
                    msgID = Msg.receiveMsgId(_dis);
                    Utils.received(msgID);
                } catch (Exception e) {
                    e.printStackTrace();
                    // jesli nie udalo  sie wczytac msg to wszystko sie psuje.
                    break;
                }

                if (msgID == MagicNumbers.BROADCAST_BID_MSG_NR) {

                    NewBidBroadcastMsg bMsg = new NewBidBroadcastMsg(_protocol);
                    bMsg.receive();
                    if (_model != null) {
                        _model.updateSerwerItemPrice(_protocol.getIP(),
                                _protocol.getPort(), bMsg.getItem());
                    } else {
                        Utils.write("model == null!");
                    }


                } else if (msgID == MagicNumbers.FINISH_MSG_NR) {
                    FinishMsg finishMsg = new FinishMsg(_protocol);

                    try {
                        finishMsg.receive();
                        ServerIntf server = _model.getServerByAddAndPort(
                                _protocol.getIP(),
                                _protocol.getPort());
                        ItemIntf item = null;
                        if (server != null) {
                            item = server.getItemByID(finishMsg.getItemID());
                            if (item != null) {
                                item.setAuctionOffline();
                                item.setWinnersHash(finishMsg.getWinnerHash());
                            } else {
                                throw new Exception("Item not found!");
                            }
                        } else {
                            throw new Exception("given host not found");
                        }

                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                } else {
                    Utils.write("otrzymano nieoczekiwany msg: " + msgID);
                    break;
                }

            } else {
                try {
                    Utils.write("brak msg do wczytania, śpię..");

                    Thread.sleep(sleepingTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
        try {
            _protocol.getSocket().close();
        } catch (IOException e) {
        }


    }
}
